﻿using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Coder.Workflow.ViewModel;
using Fee;
using Fee.FileAttachs;
using Fee.IO.Exporters;
using Fee.Orders;
using Fee.Orders.DesignWorkflow;
using Fee.Orders.ViewModel;
using Fee.Searchers;
using Fee.Stores;
using Fee.ViewModel;
using Identity;
using JwtWebApi.Data;
using JwtWebApi.Models.ViewModel;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Remotion.Linq.Clauses;
using static System.String;

namespace JwtWebApi.Controllers
{
    [Authorize]
    [Route("[controller]")]
    [ApiController]
    [EnableCors]
    public class BudgetOrderController : WorkflowBaseController<BudgetOrderManager<ApplicationDbContext>, BudgetOrder>
    {
        private readonly IBudgetOrderStore<ApplicationDbContext> _budgetOrderStore;
        private readonly ApplicationDbContext _dbContext;
        private readonly IConstructionTaskStore<ApplicationDbContext> _constructionTaskStore;
        private readonly FileManager _fileManager;
        private readonly BudgetOrderManager<ApplicationDbContext> _orderManager;


        public BudgetOrderController(BudgetOrderManager<ApplicationDbContext> orderManager,
            ApplicationDbContext dbContext, IConstructionTaskStore<ApplicationDbContext> constructionTaskStore,
            IBudgetOrderStore<ApplicationDbContext> budgetOrderStore, FileManager fileManager) : base(orderManager,
            dbContext)
        {
            _budgetOrderStore = budgetOrderStore;

            _dbContext = dbContext;
            _constructionTaskStore = constructionTaskStore;
            _fileManager = fileManager;
            _orderManager = orderManager;
        }


        [HttpGet("list-station-budget")]
        public IActionResult List([FromQuery] StationBudgetSearch searcher)
        {
            var detial = _constructionTaskStore.BudgetSearches(searcher, out var total);
            return Json(new
            {
                data = detial,
                total = total,
            });
        }
        [HttpGet("export-station-budget")]
        public IActionResult ListExport([FromQuery] StationBudgetSearch searcher)
        {
            searcher.Page = 1;
            searcher.PageSize = 10000;
            var detial = _constructionTaskStore.BudgetSearches(searcher, out var total);
            var export = new BudgetExporter<ApplicationDbContext>(_constructionTaskStore);


            var fileName = _fileManager.GetTempPrivateFile(".xlsx", this.User.Identity);
            var stream = System.IO.File.OpenWrite(fileName);
            export.ToExcel(stream, detial);
            return File(System.IO.File.OpenRead(fileName), "APPLICATION/octet-stream","初步预算表.xlsx");
        }


        public override IActionResult GetByWorkActionResult(int id)
        {
            var workflowInstanceItem = _orderManager.GetWorkActivity(id, true);

            var result = new WorkActivityViewData<OrderViewModel>(workflowInstanceItem)
            {
                ProcessInstance = new BudgetOrderViewModel((BudgetOrder)workflowInstanceItem.ProcessInstance)
            };
            return Json(result);
        }


        [HttpPut("save/{id:int}")]
        public IActionResult Save([FromBody] BudgetOrderModel data, [FromRoute] int id)
        {
            var usr = _dbContext.GetByUserName(User.Identity.Name);
            var fr = _orderManager.GetCurrentWorkActivity(id, usr);

            if (!fr.Any())
                return Ok(new
                {
                    successed = false,
                    message = "工作已经完成"
                });
            var order = _budgetOrderStore.GetById(id);
            var activity = fr.First();
            if (activity.DepositUser.Id != usr.Id && order.User.Id != usr.Id)
                return Unauthorized(new
                {
                    successed = false,
                    message = "不是你的工作"
                });


            order.UpdateBy(data.PlanCosts);
            order.UpdateBy(data.Details.Select(f => f.ToDelegateOrderDetail(_dbContext)));

            _dbContext.Update(order);
            _dbContext.SaveChanges();
            return Json(new
            {
                successed = true,
                message = "保存成功"
            });
        }


        [HttpGet("myTask")]
        public IActionResult GetMyTask([FromQuery] DelegateWorkActivitySearch searcher)
        {
            var task
                = _orderManager.GetMyTask(searcher, out var total);

            return Json(new
            {
                data = task,
                total
            });
        }


        [HttpDelete("attach/{taskId:int}/{fileAttachId:int}")]
        public IActionResult DeleteAttach
        ([FromRoute] int fileAttachId, [FromRoute] int taskId
        )
        {
            var order
                = _dbContext.Set<BudgetOrder>().Include(_ => _.Attaches).ThenInclude(_ => _.File.UploadUser)
                    .FirstOrDefault(f => f.Id == taskId);

            for (var index = 0; index < order.Attaches.Count; index++)
            {
                var attach = order.Attaches[index];
                if (attach.FileId == fileAttachId)
                {
                    System.IO.File.Delete(order.Attaches[index].File.SystemPath);
                    order.Attaches.RemoveAt(index);
                    break;
                }
            }

            _dbContext.SaveChanges();
            return Json(new
            {
                success = true,
                message = "删除成功"
            });
        }

        [HttpPost("attach/{id:int}")]
        public async Task<IActionResult> UploadAttach([FromRoute] int id
            , [FromForm] IFormFile formFile)
        {
            var filePath = _fileManager.GetAuthProjectFileTask(Path.GetExtension(formFile.FileName), id);

            var stream = new FileStream(filePath, FileMode.Create);


            var copyTask = formFile.CopyToAsync(stream).ContinueWith(task => { stream.Dispose(); });


            var attach = new FileAttach(formFile.FileName, filePath)
            {
                UploadUser = _dbContext.GetByUserName(User.Identity.Name)
            };

            var order
                = _dbContext.Set<BudgetOrder>().Include(_ => _.Attaches).ThenInclude(_ => _.File.UploadUser)
                    .FirstOrDefault(f => f.Id == id);

            order.Attaches.Add(new BudgetOrderFileAttach
            {
                File = attach,
                Order = order
            });
            await copyTask;
            _dbContext.SaveChanges();
            return Json(new
            {
                successed = true
            });
        }

        [HttpGet("attach/{orderId:int}")]
        public IActionResult ListAttach([FromRoute] int orderId)
        {
            var attaches
                = _dbContext.Set<BudgetOrder>()
                    .Include(_ => _.Attaches).ThenInclude(_ => _.File).ThenInclude(f => f.UploadUser)
                    .Where(f => f.Id == orderId).SelectMany(f => f.Attaches).Select(_ => new
                    {
                        _.File.Id,
                        _.File.CreateTime,
                        _.File.Name,
                        Uploader = _.File.UploadUser != null ? _.File.UploadUser.Name : ""
                    });


            return Json(attaches);
        }

        [HttpGet("attach/{id:int}/{fileAttachId:int}")]
        public IActionResult GetBlobDownload([FromRoute] int fileAttachId, [FromRoute] int id)
        {
            var file = _dbContext.Set<FileAttach>().FirstOrDefault(f => f.Id == fileAttachId);

            var filePath = file.SystemPath;
            var contentType = "application/octet-stream";
            var fileName = file.Name;
            return File(System.IO.File.OpenRead(filePath), contentType, fileName);
        }
    }
}